home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlb20 / lib / thread.c < prev    next >
C/C++ Source or Header  |  1992-04-27  |  3KB  |  112 lines

  1. /*
  2.  * tfork(function, argument): starts a new thread of execution running
  3.  * in the same address space. The new thread gets its own 4K stack,
  4.  * and starts at the address in "function" with "argument" on the stack,
  5.  * i.e. as though the main program had a call like "function(argument)".
  6.  * The main program continues executing, with tfork returning the process
  7.  * i.d. of the child.
  8.  * (if MiNT is not active, then the child runs to completion
  9.  *  and the return value is the child's exit status; vfork() relies on
  10.  *  this behavior)
  11.  *
  12.  * Note that parent and child share the same memory; this could cause
  13.  * problems with some library calls, notably malloc().
  14.  */
  15.  
  16. #include <osbind.h>
  17. #include <basepage.h>
  18. #include <signal.h>
  19. #include <time.h>
  20. #include <unistd.h>
  21. #include <signal.h>
  22. #include <errno.h>
  23.  
  24. #define SIZE 4096L
  25.  
  26. extern int __mint;
  27. extern long _childtime;            /* in main.c */
  28. extern long _sigpending, _sigmask;    /* in signal.c */
  29. extern __Sigfunc _sig_handler[NSIG];    /* ditto */
  30.  
  31.  
  32. /* this is used by wait() and wait3() to retrieve the child's exit code */
  33. long __waitval = -ENOENT;
  34.  
  35. /* and this is used to retrieve the child's time */
  36. long __waittime = 0;
  37.  
  38. static void
  39. startup(b)
  40.     register BASEPAGE *b;
  41. {
  42.     register int (*func)();
  43.     register long arg;
  44.     extern void _setstack();    /* in crt0.s */
  45.  
  46.     _setstack( ((long)b) + SIZE );
  47.     func = (int (*)())b->p_dbase;
  48.     arg = b->p_dlen;
  49.     Pterm((*func)(arg));
  50. }
  51.  
  52. /* use long instead of int so vfork works OK with -mshort */
  53.  
  54. long
  55. tfork(func, arg)
  56.     int (*func)();
  57.     long arg;
  58. {
  59.     register BASEPAGE *b;
  60.     register long pid;
  61.     register long savpending, savmask;
  62.     register BASEPAGE *savbase;
  63.     __Sigfunc savhandler[NSIG];
  64.     long now;
  65.     int i;
  66.  
  67.     b = (BASEPAGE *)Pexec(PE_CBASEPAGE, 0L, "", 0L);
  68.     (void)Mshrink(b, SIZE+256);
  69.     b->p_tbase = (char *)startup;
  70.     b->p_dbase = (char *)func;
  71.     b->p_dlen = arg;
  72.     b->p_hitpa = ((char *)b) + SIZE + 256;
  73.  
  74.     if (__mint)
  75.         pid = Pexec(104, 0L, b, 0L);
  76.     else {
  77.     /* save the signal masks and signal handlers, the child may change
  78.            them */
  79.         savpending = _sigpending;
  80.         _sigpending = 0;
  81.         savmask = _sigmask;
  82.         _sigmask = 0;
  83.         for (i = 0; i < NSIG; i++)
  84.             savhandler[i] = _sig_handler[i];
  85.         savbase = _base;
  86.         _base = b;
  87.  
  88.         now = clock();
  89.         pid = Pexec(4, 0L, b, 0L);
  90.         (void)Mfree((long)b->p_env);    /* free the memory */
  91.         (void)Mfree((long)b);
  92.  
  93.         _base = savbase;
  94.     /* restore signal stuff */
  95.         for (i = 0; i < NSIG; i++)
  96.             _sig_handler[i] = savhandler[i];
  97.         _sigmask = savmask;
  98.         _sigpending = savpending;
  99.         if (pid >= 0) {
  100.             int retval = pid;
  101.  
  102.         /* see the TOS algorithm for getpid() */
  103.             pid = ((long)b) >> 8;
  104.             __waitval = (pid << 16) | retval;
  105.             raise(SIGCHLD);
  106.             __waittime = clock() - now;
  107.             _childtime += __waittime;
  108.         }
  109.     }
  110.     return pid;
  111. }
  112.